package cn.com.sbell.vss.auth.radius;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sourceforge.jradiusclient.RadiusAttribute;
import net.sourceforge.jradiusclient.RadiusAttributeValues;
import net.sourceforge.jradiusclient.RadiusPacket;
import net.sourceforge.jradiusclient.attributes.VendorSpecificAttribute;
import net.sourceforge.jradiusclient.packets.PapAccessRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.com.sbell.vss.ICommander;
import cn.com.sbell.vss.ILogCommander;
import cn.com.sbell.vss.Response;
import cn.com.sbell.vss.VissSession;
import cn.com.sbell.vss.Util;
import cn.com.sbell.vss.VssConstants;
import cn.com.sbell.vss.VssException;
import cn.com.sbell.vss.ems.dao.IUserDao;
import cn.com.sbell.vss.ems.dao.IUserRoleDao;
import cn.com.sbell.vss.ems.entity.User;
import cn.com.sbell.vss.ems.entity.UserRole;
import cn.com.sbell.vss.servlet.DispatchServlet;
import cn.com.sbell.vss.util.RandomGUID;
import cn.com.sbell.vss.util.SessionHolder;
import cn.com.sbell.vss.util.VssValidator;
import cn.com.sbell.vss.auth.radius.bean.ServerAddress;
import cn.com.sbell.vss.csg.vap.util.CrossDomainCredential;
import cn.com.sbell.vss.csg.vap.util.RouteSessionMapper;


/**
 * @author Yifu.HUANG
 * 
 */
public class AuthenticatedByRadius implements ICommander, ILogCommander {
	private static final Log log = LogFactory
			.getLog(AuthenticatedByRadius.class);



	private String localIp = "127.0.0.1";

	private int nasType = -1;

	private VssRadiusClient vssRadiusClient;

	private SessionHolder sessionHolder;

//	private IUserDao userDao;
//
//	private IUserRoleDao userRoleDao;

	/**
	 * (non-Javadoc)
	 * 
	 * @see cn.com.sbell.vss.ICommander#execute(javax.servlet.http.HttpServletRequest)
	 */
	public Response execute(HttpServletRequest request) {
		// prepare response (include parameters)
		Response response = Response.createResponse(request);

		// get parameters
		String username = Util.getTrimParameter(request, "__username");
		String password = Util.getTrimParameter(request, "__password");
		
		
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//front_type will distinguish ah auth from vs auth.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		if (Util.strIsNull(username)) {
			username = Util.getTrimParameter(request, "username");
		}
		if (Util.strIsNull(password)) {
			password = Util.getTrimParameter(request, "password");
		}
		String host = Util.getTrimParameter(request, "host");
		String _alarmPort = Util.getTrimParameter(request, "alarmPort");

		if (host.length() == 0) {// get the client host
			host = request.getRemoteAddr();
			if (host == null || host.length() == 0) {
				host = request.getRemoteHost();
			}
		}

		VssValidator.validateMaxLength("field.user.username", username, true,
				32);
		VssValidator.validateMaxLength("field.user.password", password, false,
				32);
		VssValidator.validateNumber("field.alarmPort", _alarmPort, false,
				VssConstants.DATA_INTEGER);
		VssValidator.validateRequired("field.host", host);

		// set session data
		String sessionId = Util.getSessionId(request);
		if (sessionId == null) {
			sessionId = new RandomGUID().toString();
		}
		VissSession session = new VissSession(sessionId);

//		if (nasType == -1) {
//			if (userDao != null) {
//				nasType = 1;// EMS
//			} else {
				nasType = 2;// CSG
//			}// MA ??
//		}
		if(log.isDebugEnabled()){
		log.debug("Authenticate by radius server ... ");
		}
		ServerAddress serverAddress=RadiusAuthenticate.getServerAddress(request);
				
//		added vondart
		CrossDomainCredential cdc= new CrossDomainCredential();
		CrossDomainCredential cdcExisting=null;

		
		String route=null;
		try {
			route=Util.getRoute(request);
			
			if(null!=route){
				cdcExisting=RouteSessionMapper.checkRoute(route, request);
				if(null==cdcExisting){
			RadiusAuthenticate.authenticate(username, password, serverAddress.getServerIp(), serverAddress.getServerPort(),
					serverAddress.getServerId(), session,localIp,
					nasType,vssRadiusClient,cdc,false,serverAddress.getFront_type());
			log.debug("relay Auth by Radius succeed!");
				if((null!=cdc.getNextDomainUserName())&&(null!=cdc.getNextDomainPassWord()))
				{
					cdc.setNextDomainPassWord(cdc.getNextDomainPassWord());//Util.MD5(
					RouteSessionMapper.updateRoute(route, cdc,request);
					log.debug("authenticat by radius update nextDomainUserName, nextDomainPassWord");
				}
				}
				log.debug("relay credential existing!");
			}else{
				RadiusAuthenticate.authenticate(username, password, serverAddress.getServerIp(), serverAddress.getServerPort(),
						serverAddress.getServerId(), session,localIp,
						nasType,vssRadiusClient,cdc,true,serverAddress.getFront_type());
				log.debug("local Authen by Radius succeed!");
			}
		} catch (VssException e) {
			// TODO: handle exception
			Response res = Response.createResponse(request);
			res.setReturnCode(e.getResultCode());
			String returnMessage = DispatchServlet
			.getMessage("code." + res.getReturnCode(),
					e.getFields(),request);
			res.setReturnMessage(returnMessage);
			return res;
		}
//		added vondart
		
		User user = null;

		session.setLoginTime(System.currentTimeMillis());
		session.setLastAccessTime(session.getLoginTime());
		session.setIp(host);
		session.setAlarmPort((_alarmPort.length()) == 0 ? -1 : Integer
				.parseInt(_alarmPort));
		session.setDomainId("<LOCALE>");

		sessionHolder.putSession(session);
		sessionHolder.cleanTimeoutSession();

		request.setAttribute(VssConstants.KEY_USER_SESSION_DATA, session);

		// get user info form database
		Map parameters = new LinkedHashMap();
//		if (userDao != null) {
//			user = loadUserInfo(username, session);
//			if (user != null) {
//				parameters.put("userId", user.getId());
//			}
//		}
		parameters.put("username", username);
		parameters.put("sessionId", sessionId);
		parameters.put("sessionTimeout", String.valueOf(sessionHolder
				.getSessionTimeout() / 1000L));

		// set parameters xml string, then return
		response.setParameters(parameters);
		return response;

	}





	public void setSessionHolder(SessionHolder sessionHolder) {
		this.sessionHolder = sessionHolder;
	}

	public void setLocalIp(String localIp) {
		if(!Util.strIsNull(localIp)){
			localIp = localIp.trim(); 
		}
		this.localIp = localIp;
	}

	public void setNasType(int nasType) {
		this.nasType = nasType;
	}

	public void setVssRadiusClient(VssRadiusClient client) {
		this.vssRadiusClient = client;
	}

//	public void setUserDao(IUserDao userDao) {
//		this.userDao = userDao;
//	}
//
//	public void setUserRoleDao(IUserRoleDao userRoleDao) {
//		this.userRoleDao = userRoleDao;
//	}
}
